<?php
/**
 *
 *
 * $Rev: 7 $
 * $Author: thejahweh $
 * $Date: 2010-09-01 07:30:00 +0000 (Wed, 01 Sep 2010) $
 * $Id: navigation.class.php 7 2010-09-01 07:30:00Z thejahweh $
 * $URL: http://allone.googlecode.com/svn/trunk/plugins/navigation/navigation.class.php $
 * @author: Adrian Liechti <info@jahweh.ch>
 * @copyright: 2010 Adrian Liechti, GPL3 and CC3 BY-SA
 */

class navigation {

	public $id;
	public $name;
	public $default;
	public $active;
	public $isLoaded = false;
	public $nodes;
	public $nodesById;
	public $right_edit_id;
	public $rightEdit;
	public static $current;
	public static $defaultPage;
	public static $nodeTypeNormal = 0;
	public static $nodeTypeUrl = 1;
	public static $nodeTypeLink = 2;
	public static $url;
	public static $currentUrl;
	public static $p;
	public static $pVar			= 'p';
	public static $pSpacer		= '/';
	public static $urlSpacer	= '?p=';
	public static $urlSpacer2	= '&';
	public static $protocol		= 'http://';
	public static $currentPage;
	public static $currentPageTree;
	public static $error;
	public static $target = array ('_self','_blank','_parent','_top');
	private static $loaded = false;

	public function __construct () {

	}
	
	/**
	 * Lädt eine ganze Navigation, wenn keine $id angegeben wurde, wird die DefaultNav geladen
	 * @param int $id
	 * @return bool
	 */
	public function getNavigation ($id = false) {
		global $db, $user;
		if ($id === false) {
			$navigation_q = $db->query("
				SELECT
					navigation_id,
					name, 
					is_default,
					active
				FROM 
					navigations
				WHERE
					is_default = 1
				LIMIT 1;");
		} else {
			$navigation_q = $db->query("
				SELECT
					navigation_id,
					name, 
					is_default,
					active
				FROM 
					navigations
				WHERE
					navigation_id = ".$db->quote($id)."
				LIMIT 1;");
		}
		if ($navigation_q !== false) {
			$navigation_q->setFetchMode(PDO::FETCH_ASSOC);
			$navigation				= $navigation_q->fetch();
			$this->id				=& $navigation['navigation_id'];
			$this->name				=& $navigation['name'];
			$this->default			=& $navigation['is_default'];
			$this->active			=& $navigation['active'];
			$this->right_edit_id	=& $navigation['right_edit_id'];
			$this->rightEdit		= new permission ($this->right_edit_id, false);
		} else {
			u::o($db->error, 'user:getNavigation', 1);
			return $this->isLoaded = false;
		}

		$nav_q = $db->query("
			SELECT
				*,
			    EXISTS (
			        SELECT 
			            p.permission_id
			        FROM 
			            roles_has_permissions AS p,
			            users_has_roles AS uhr,
			            roles AS r
			        WHERE 
			            uhr.user_id = ".$db->quote($user->id)."
			            AND r.removed = 0
			            AND p.role_id = uhr.role_id
			            AND p.permission_id = right_view_id
			    ) AS right_access
			FROM 
			    navigations_nodes
			WHERE
				navigation_id = ".$db->quote($this->id)." AND
				removed = 0
			ORDER BY
			  parent_id,
			  sort;");
		if ($nav_q !== false) {
			$this->navigation = array();
			$nav_q->setFetchMode(PDO::FETCH_ASSOC);
			while ($row = $nav_q->fetch()) {
				$n = new navigationNode();
				$n->getByArray($row);
				$n->rightAccess->has = ($row['right_access'] == 1 ? true : false);
				$this->nodes[$row['parent_id']][$row['navigation_node_id']] = $n;
				$this->nodesById[$row['navigation_node_id']] =& $this->nodes[$row['parent_id']][$row['navigation_node_id']];
			}
			/**
			 * TODO Volle URL von den Navigationspunkten ermitteln!
			 */
			/*foreach ($this->nodes as $parentId => $nodes) {
				while (true) {
					if ($npid)
				}
				foreach ($nodes as $nodeId => $node) {
					
				}
			}*/
			return $this->isLoaded = true;
		} else {
			u::o($this->id, 'user:getNavigation', 1);
			if (isset($db->error)) {
				u::o($db->error, 'user:getNavigation', 1);
			}
			return $this->isLoaded = false;
		}
	}
	
	/**
	 * Generiert einen Dump, zu testzwecken
	 * @return string
	 */
	public function dump () {
		$out = '';
		$this->dumpNodes($this->nodes, NULL, $out);
		return $out;
	}
	
	/**
	 * DumpNode generierung
	 * @param array &$nodes
	 * @param int $parent
	 * @param string &$out
	 * @param int $leftSpan
	 * @return none
	 */
	private function dumpNodes(&$nodes, $parent = NULL, &$out, $leftSpan = 0) {
		$span = '   ';
		$s1 = str_repeat($span, $leftSpan);
		$s2 = str_repeat($span, $leftSpan+1);
		$out .= $s1."<ul>\n";
		foreach ($nodes[$parent] as $p => $n) {
			$out .= $s2.'<li>'.htmlSpecialChars($n->name);
			if (isset($nodes[$n->id])) {
				$out .= "\n";
				$this->dumpNodes($nodes, $n->id, $out, $leftSpan+2);
				$out .= $s2;
			}
			$out .= "</li>\n";
		}
		$out .= $s1."</ul>\n";
	}
	
	/**
	 * Ladet die standart Navigation und die derzeitige Seite, url und currentUrl
	 * @param string $p
	 * @return bool
	 */
	public static function load () {
		global $navigation;
		if (self::$loaded === false) {
			self::$p =& $_GET[self::$pVar];
			/**
			 * Get Default Navigation
			 */
			$navigation = new navigation();
			$navigation->getNavigation();
			self::$current =& $navigation;
			
			/**
			 * Get Current URL and Page
			 */
			$t = new timeStamp('navigation:getCurrent');
			self::getCurrent();
			$t->end();
			self::$url = $_SERVER['SERVER_NAME'].$_SERVER['SCRIPT_NAME'];
			self::$currentUrl = self::$protocol.self::$url.(isset(self::$p) ? self::$urlSpacer.self::$p : '' );
			
			return self::$loaded = true;
		}
		return false;
	}
	
	/**
	 * Gibt die derzeitige Url mit Variablen zurück.
	 * @param array(name=>value) $vars
	 * @return string
	 */
	public static function getUrl ($vars = false) {
		if (is_array($vars)) {
			if (isset($vars[self::$pVar])) {
				$curl = self::$protocol.self::$url.self::$urlSpacer.$vars[self::$pVar];
				if (count($vars) === 1) {
					return $curl;
				} else {
					unset($vars[self::$pVar]);
				}
			} else {
				$curl =& self::$currentUrl;
			}
			array_walk($vars, array('self', 'getUrlFetch'));
			$v = implode('&', $vars);
			return $curl.self::$urlSpacer2.$v;
		} else {
			return self::$currentUrl;
		}
	}
	
	/**
	 * Bearbeitungsfunktion für getUrl
	 * @param string &$value
	 * @param string $key
	 * @return none
	 */
	private static function getUrlFetch (&$value, $key){
		$value = $key.'='.$value;
	}
	
	/**
	 * Lädt die derzeitige URL und Seitenvariablen
	 * @return bool
	 */
	private static function getCurrent () {
		global $db, $t, $user;
		if (!empty(self::$p) and ($pa = explode(self::$pSpacer,self::$p)) and is_array($pa)) {
			$urlQuoted = implode(',', array_map(array($db,  'quote'), $pa));
			$pages_q = $db->query("
				SELECT
					url, navigation_node_id, parent_id, name, url, type, highlight,
					sort, target, template_id, layout_id, description, removed,
					right_view_id, right_access_id, right_edit_id, navigation_id,
					EXISTS (
						SELECT 
							p.permission_id
						FROM 
							roles_has_permissions AS p,
							users_has_roles AS uhr,
							roles AS r
						WHERE 
							uhr.user_id = ".$db->quote($user->id)."
				            AND r.removed = 0
							AND p.role_id = uhr.role_id
							AND p.permission_id = right_access_id
					) AS right_access
				FROM 
					navigations_nodes
				WHERE
					url IN (".$urlQuoted.");");
			
			if ($pages_q !== false) {
				$sqlPages	= $pages_q->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_UNIQUE|PDO::FETCH_ASSOC);
				$pages		= array();
				$page		= false;
				foreach ($pa as $p) {
					$nn = new navigationNode();
					$nn->getByArray($sqlPages[$p]);
					$nn->rightAccess = ($sqlPages[$p]['right_access'] == 1 ? true : false);
					$pages[] =& $nn;
					if (isset($nn) === false) {
						self::$error = $nn->error = 404;
						break;
					} elseif ($nn->rightAccess === false) {
						self::$error = $nn->error = 403;
						break;
					}
				}
				
				self::$currentPage		=& $pages[count($pages)-1];
				self::$currentPageTree	=& $pages;
				
				return true;
			} else {
				$page			= new navigationNode();
				$page->error	= 404;
				$page->name		= $pageName;
				return true;
			}
		} else {
			if (isset($t->cfg->defaultPage) === false) {
				$cm = $t->cfg->addChild('defaultPage');
				/**
				 * TODO Die erste Seite automatisch ermitteln
				 */
				$cm->addAttribute('id','1');
				$t->cfg->save();
			}
			self::getCurrentById($t->cfg->defaultPage['id']);
			return false;
		}
	}
	
	/**
	 * Lädt eine Seite über die ID, mit den Seitenvariablen und generiert die URL
	 * @param int $id
	 * @return bool
	 */
	private static function getCurrentById($id) {
		$pages[] = array();
		$l = -1;
		$i = $id;
		$p = '';
		while(true) {
			$l++;
			$pages[$l]	= new navigationNode($i);
			$p			= $pages[$l]->url.($p === '' ? '' : self::$pSpacer.$p);
			if (isset($pages[$l]->isLoaded) === false) {
				$pages[$l]->error = 404;
				break;
			} elseif ($pages[$l]->rightAccess->has() === false) {
				$pages[$l]->error = 403;
				break;
			} elseif ($pages[$l]->parent_id === NULL) {
				break;
			} else {
				$i = $pages[$l]->parent_id;
			}
		}
		self::$currentPage		=& $pages[0];
		self::$currentPageTree	= array_reverse($pages);
		self::$p				=& $p;
		return true;
	}

}

/**
 * TODO Vielleicht in ein eigenes File verfrachten.
 * @param $params
 * @param $smarty
 * @return string
 */
function smarty_geturl ($params, &$smarty) {
	return navigation::getUrl($params);
}
?>